package com.lushuan.ch11_springboot_test.demo.fileIO;

import java.io.*;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;

public class FileCopys {



    public static void main(String[] args) throws IOException {
        // 这是传统的I/O方式，逐字节读取和写入数据，适合小文件的复制，但效率较低。
        fileCopyUsingStreams("source.txt", "destination.txt");
        fileCopyUsingBufferedStream("source.txt", "destination.txt");
        fileCopyUsingFiles("source.txt", "destination.txt");
        fileCopyUsingFileChannel("source.txt", "destination.txt");
        //
        fileCopyUsingMappedByteBuffer("source.txt", "destination.txt");


    }

    /**
     * 这是传统的I/O方式，逐字节读取和写入数据，适合小文件的复制，但效率较低。
     * @param source
     * @param dest
     * @throws IOException
     */
    public static void fileCopyUsingStreams(String source, String dest) throws IOException {
        try (FileInputStream fis = new FileInputStream(source);
             FileOutputStream fos = new FileOutputStream(dest)) {
            byte[] buffer = new byte[1024];
            int length;
            while ((length = fis.read(buffer)) > 0) {
                fos.write(buffer, 0, length);
            }
        }
    }

    /**
     * 使用带缓冲的流可以减少I/O次数，提高性能。适合稍大的文件拷贝，但仍然是逐字节操作，速度相对较慢。
     * @param source
     * @param dest
     * @throws IOException
     */
    public static void fileCopyUsingBufferedStream (String source, String dest) throws IOException {
        try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(source));
             BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(dest))) {
            byte[] buffer = new byte[1024];
            int length;
            while ((length = bis.read(buffer)) > 0) {
                bos.write(buffer, 0, length);
            }
        }
    }

    /**
     * Java 7引入了Files类，可以通过Files.copy方法快速复制文件，内部使用了NIO通道和缓冲区，性能较高。
     * 代码简洁，使用了NIO优化，适合大文件复制
     * @param source
     * @param dest
     * @throws IOException
     */
    public static void fileCopyUsingFiles (String source, String dest) throws IOException {
        Path sourcePath = Paths.get(source);
        Path destPath = Paths.get(dest);
        Files.copy(sourcePath, destPath, StandardCopyOption.REPLACE_EXISTING);
    }

    /**
     * 通过FileChannel的transferTo和transferFrom方法，可以直接在两个通道之间传输数据，避免了用户态与内核态的多次数据交换，效率很高，是目前最快的文件复制方式
     * 效率最高，使用了零拷贝技术，适合超大文件的复制
     * @param source
     * @param dest
     * @throws IOException
     */
    public static void fileCopyUsingFileChannel (String source, String dest) throws IOException {
        try (FileChannel sourceChannel = new FileInputStream(source).getChannel();
             FileChannel destChannel = new FileOutputStream(dest).getChannel()) {
            sourceChannel.transferTo(0, sourceChannel.size(), destChannel);
        }
    }

    /**
     * 通过内存映射文件的方式进行复制，适合超大文件的拷贝。利用操作系统的文件内存映射机制，直接将文件映射到内存中，性能较高，但代码较复杂。
     * 性能较高，适合非常大的文件复制。
     * @param source
     * @param dest
     * @throws IOException
     */
    public static void fileCopyUsingMappedByteBuffer(String source, String dest) throws IOException {
        try (FileChannel sourceChannel = new RandomAccessFile(source, "r").getChannel();
             FileChannel destChannel = new RandomAccessFile(dest, "rw").getChannel()) {
            long size = sourceChannel.size();
            MappedByteBuffer sourceBuffer = sourceChannel.map(FileChannel.MapMode.READ_ONLY, 0, size);
            MappedByteBuffer destBuffer = destChannel.map(FileChannel.MapMode.READ_WRITE, 0, size);
            destBuffer.put(sourceBuffer);
        }
    }





}